package de.bremen.bremenbybike;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;

import com.actionbarsherlock.app.SherlockFragment;

public class SearchFragment extends SherlockFragment {
	
	@Override
	public View onCreateView(final LayoutInflater inflater,
			final ViewGroup container, final Bundle savedInstanceState) {
		View view = inflater.inflate(R.layout.search_layout, container, false);
		        
        final AutoCompleteTextView startTextView = (AutoCompleteTextView) view.findViewById(R.id.search_start_textview);
        startTextView.addTextChangedListener(new TextWatcher() {
        	// methods for TextWatcher
    		@Override
    		public void afterTextChanged(Editable s) {
    			 new SuggestionUpdaterTask(startTextView).execute(s.toString());
    		}

    		@Override
    		public void beforeTextChanged(CharSequence s, int start, int count,	int after) {}

    		@Override
    		public void onTextChanged(CharSequence s, int start, int before, int count) {}
		});

               
        final AutoCompleteTextView endTextView = (AutoCompleteTextView) view.findViewById(R.id.search_end_textview);
        endTextView.addTextChangedListener(new TextWatcher() {
        	// methods for TextWatcher
    		@Override
    		public void afterTextChanged(Editable s) {
    			 new SuggestionUpdaterTask(endTextView).execute(s.toString());
    		}

    		@Override
    		public void beforeTextChanged(CharSequence s, int start, int count,	int after) {}

    		@Override
    		public void onTextChanged(CharSequence s, int start, int before, int count) {}
		});        	
        
        
        Button searchButton = (Button) view.findViewById(R.id.button1);
        searchButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				MainActivity activity = (MainActivity) getActivity();
				activity.mViewPager.setCurrentItem(1);
			}
		});
        
		return view;
	}
	
	public class SuggestionUpdaterTask extends AsyncTask<String, Void, ArrayList<String>> {
		private final static String TAG = "SuggestionUpdater";
		
		AutoCompleteTextView view;
		
		// constructor
		public SuggestionUpdaterTask(AutoCompleteTextView view) {
			this.view = view;
		}

		@Override
		protected ArrayList<String> doInBackground(String... arg0) {
			// get suggestion list from maps server
			JSONParser parser = new JSONParser();
			ArrayList<String> foo = parser.getSuggestions(arg0[0]);

			return foo;
		} 

		@Override
		protected void onPostExecute(ArrayList<String> result) {
			super.onPostExecute(result);
			
	        ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity().getApplicationContext(), 
	        		android.R.layout.simple_dropdown_item_1line, result);
	        view.setAdapter(adapter);
	        view.showDropDown();
		}
	}

	private static class JSONParser {
		private final static String TAG = "JSONParser";

		// JSON Node names
		private static final String TAG_ANSWER = "answer";
		private static final String TAG_STREETS = "streets";
		private static final String TAG_VALUE = "value";

		ArrayList<String> streetsList = new ArrayList<String>();

		//load suggestions as JSON from maps.bremen.de a2-search with stub as start
		public String getJSONFromSearchA2(String stub) {
			String json = "";

			try {
				URI uri = new URI("http", "maps.bremen.de", "/a2", "q="+stub, null);
				URL url = uri.toURL();				
				HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
				InputStream in = new BufferedInputStream(urlConnection.getInputStream());
				BufferedReader reader = new BufferedReader(new InputStreamReader(in, "utf-8"));
				StringBuilder sb = new StringBuilder();
				String line = null;
				while ((line = reader.readLine()) != null) {
					sb.append(line + "n");
				}
				in.close();
				json = sb.toString();
			} catch (MalformedURLException e) {
				Log.e(TAG, "Malformed exception: " + e.toString());
			} catch (IOException e) {
				Log.e(TAG, "Error reading from url: " + e.toString());
			} catch (URISyntaxException e) {
				Log.e(TAG, "URI syntax is wrong: " + e.toString());
			} 

			return json;
		}

		//interpret JSON recursively and return the answer values
		public ArrayList<String> getSuggestions(String stub) {
			// Creating JSON Parser instance
			JSONParser jParser = new JSONParser();

			// getting JSON string from URL
			String jsonString = jParser.getJSONFromSearchA2(stub);

			// populate list with ALL streets
			streetsList = expandJSONNode(jsonString);
			return streetsList;
		}

		private ArrayList<String> expandJSONNode(String val) {
			// JSON object
			JSONObject jsonAnswer = null;
			JSONObject jsonStreets = null;

			ArrayList<String> list = new ArrayList<String>();
			String streets;
			String street;

			try {
				// get content of answer node
				// try parse the string to a JSON object
				jsonAnswer = new JSONObject(val);
				jsonStreets = jsonAnswer.getJSONObject(TAG_ANSWER);
				streets = jsonStreets.getString(TAG_STREETS);

				//is it a nested JSON object?
				if (streets.startsWith("{")) {
					JSONObject jsonValue = jsonStreets.getJSONObject(TAG_STREETS);
					JSONArray jsonArrayStreets = jsonValue.getJSONArray(TAG_VALUE);
					for (int c = 0; c < jsonArrayStreets.length(); c++) {
						street = jsonArrayStreets.getString(c);
//						Log.d(TAG, String.format("%d of %d streets: %s", c+1, jsonArrayStreets.length(), street));
						if (street.endsWith("...")) {
							list.addAll(expandJSONNode(getJSONFromSearchA2(street)));
						} else {
							Log.d(TAG, "Adding street " + street);
							list.add(street);
						}
					}
				} else {
					//already only a single name, no need to unravel
					Log.d(TAG, "Single street: " + streets);
					JSONObject jsonValue = jsonStreets.getJSONObject(TAG_STREETS);
					street = jsonValue.getString(TAG_STREETS);
					Log.d(TAG, "jsonValue: " + jsonValue.toString());
					if (street.endsWith("...")) {
						list.addAll(expandJSONNode(getJSONFromSearchA2(val)));
					} else {
						Log.d(TAG, "Adding single street " + street);
						list.add(val);
					}
				}
			} catch (JSONException e) {
				Log.d(TAG, "Could not expand JSON: " + val + e.toString());
			}

			return list;
		}
	}
}
